/**
	License:		GNU General Public License version 3 (see license.txt, also available online at http://www.gnu.org/licenses/gpl-3.0.html)
	Authors:		OrbitalLab (http://www.orbitallab.ru/dee0xd/), 2008-2009

	File:			util.d
	Description:	some unsorted stuff
	Date:			09.12.2008 by Digited
**/
module dee0xd.Util;

public import
	tango.text.Util,
	tango.util.PathUtil,
	tango.io.FilePath,
	tango.io.device.File;

import
	tango.io.FileScan,
	tango.text.Regex,

	dee0xd.Log;

private class IgnoreTester
{
	protected:
		Regex[] ignore_array;
		char[]	ext,
				initialDir;
		
	public:
		this( char[] ignores, char[] extension, char[] fromDir )
		{
			ext = extension;
			initialDir = fromDir;
			
			if( ignores && ignores.length )
				foreach( ignore; split( ignores, ";" ))
					if( ignore.length )
						ignore_array ~= Regex( ignore );
		}
		
		bool Test( FilePath fp, bool isDir )
		{
			bool suitable = false;

			if( isDir || fp.suffix == ext )
			{
				suitable = true;

				foreach( ign; ignore_array )
					if( ign.test( fp.toString[initialDir.length..$] ))
					{
						log.trace( fp.toString ~ " ignored!" );
						suitable = false;
						break;
					}
			}

			return suitable;
		}
}


//---------------------------------------------------------------------------------------------------
/// search util function
//---------------------------------------------------------------------------------------------------
FilePath[] Dee0xDFileScan( FilePath startDir, FilePath.Filter filter, bool recursive = true )
{
	FilePath[] result, localFiles;

	try
	{
		foreach( path; startDir.toList( filter ))
			if( !path.isFolder )
				localFiles ~= path;
			else
				if( recursive )
					result ~= Dee0xDFileScan( path, filter, true );
	}
	catch( Exception e )
		log.trace( "Dee0xD internal filescan error: " ~ e.msg );
	
	return result ~ localFiles;
}

//---------------------------------------------------------------------------------------------------
/// search util function
//---------------------------------------------------------------------------------------------------
FilePath[] SearchFiles( char[] fromDir, char[] startDir, char[] extension, bool recursive = true, char[] ignores = null )
in
{
	assert( fromDir.length );
	assert( extension.length );
}
body
{
	FilePath[] result;

	if( !fromDir.length || ( fromDir.length && fromDir[0] == '.' ))
		fromDir = startDir ~ '/' ~ fromDir;
		
	auto fp = new FilePath( normalize( fromDir ));

	if( ignores && ignores.length )
	{
		scope tester = new IgnoreTester( ignores, extension, fromDir );
		result = Dee0xDFileScan( fp, &tester.Test, recursive );
	}
	else
		result = Dee0xDFileScan( fp, ( FilePath fp, bool isDir ) { return isDir || fp.suffix == extension; }, recursive );

	return result;
}


version( Windows )
{
	import tango.sys.win32.UserGdi;

	//---------------------------------------------------------------------------------------------------
	/// win pwd
	//---------------------------------------------------------------------------------------------------
	char[] GetApplicationPath()
	{
		char[255] ch;
		char* chp = &ch[0];
		auto result = GetCurrentDirectoryA(255,chp);
		return chp[0..result].dup;
	}
}


//---------------------------------------------------------------------------------------------------
/// remove up-to-date files from list by comparing modification time with output files.
/// returns array of up-to-date files
// files must have absolute path, startDir also must have an absolute path
//---------------------------------------------------------------------------------------------------
FilePath[] FindUpToDate( ref FilePath[] files, char[] startDir, char[] outDir, char[] outExt )
in
{
	assert( startDir.length );
}
body
{
	FilePath[]
		upToDateFiles,
		sortedInputFiles;

	foreach( file; files )
	{		
		debug assert( file.isAbsolute && file.exists && !file.isFolder );
		char[] newPath = file.path[startDir.length+1..$] ~ file.name ~ outExt;

		if( outDir.length )
			newPath = outDir ~ '/' ~ newPath;

		newPath = normalize( newPath );
		auto outFile = new FilePath( newPath );

		if( outFile.exists && !outFile.isFolder && ( outFile.modified > file.modified ))
			upToDateFiles ~= outFile;	// output file is newer than source, so source is up to date
		else
			sortedInputFiles ~= file;	// source is newer than output file (or output doesn't exist), so it really needs to be processed
	}

	files = sortedInputFiles;
	return upToDateFiles;
}